package org.nanyuan.forum.service.impl;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import org.nanyuan.forum.Utils.MD5Util;
import org.nanyuan.forum.Utils.StringUtil;
import org.nanyuan.forum.Utils.UUIDUtil;
import org.nanyuan.forum.common.AppResult;
import org.nanyuan.forum.common.ResultCode;
import org.nanyuan.forum.dao.UserMapper;
import org.nanyuan.forum.exception.ApplicationException;
import org.nanyuan.forum.model.User;
import org.nanyuan.forum.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;

@Slf4j
@Service
public class UserServiceImpl implements IUserService {
    @Resource
    private UserMapper userMapper;
    @Override
    public void createNormalUser(User user) {
        //1.非空校验
        if (user == null || !StringUtils.hasLength(user.getUsername())
        || !StringUtils.hasLength(user.getNickname()) || !StringUtils.hasLength(user.getPassword())
        || !StringUtils.hasLength(user.getSalt())) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常，统一抛出ApplicationException
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }

        //2.按用户名查询用户信息
        User existsUser = userMapper.selectByUserName(user.getUsername());
        if (existsUser != null) {
            //打印日志
            log.info(ResultCode.FAILED_USER_EXISTS.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_EXISTS));
        }

        //3.新增用户
        user.setGender((byte) 2);
        user.setArticleCount(0);
        user.setIsAdmin((byte) 0);
        user.setDeleteState((byte) 0);
        user.setState((byte) 0);
        //当前日期
        Date date = new Date();
        user.setCreateTime(date);
        user.setUpdateTime(date);

        //写入数据库
        int row = userMapper.insertSelective(user);
        if (row != 1) {
            //打印日志
            log.info(ResultCode.FAILED_CREATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }
        log.info("新增用户成功。username = {}.", user.getUsername());
    }

    @Override
    public User selectByUsername(String username) {
        //非空校验
        if (!StringUtils.hasLength(username)) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出自定义异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //返回查询到的用户信息
        return userMapper.selectByUserName(username);
    }

    @Override
    public User login(String username, String password) {
        //非空校验
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {

            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());

            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }

        //查询用户
        User user = selectByUsername(username);

        //对查询结果进行非空校验
        if (user == null) {
            log.warn("{},username；{}", ResultCode.FAILED_LOGIN.toString(), username);

            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));
        }
        //校验密码
        String encryptPassword = MD5Util.md5Salt(password,user.getSalt());

        if (!encryptPassword.equalsIgnoreCase(user.getPassword())) {
            //打印日志
            log.warn(ResultCode.FAILED_LOGIN.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));
        }
        //打印登录成功的日志
        log.info("username:{}登录成功", username);

        return user;
    }

    @Override
    public User selectById(Long id) {
        //非空校验
        if (id == null) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //调用Dao层查询数据库，并获取对象
        User user = userMapper.selectByPrimaryKey(id);
        //返回结果
        return user;
    }

    @Override
    public void addOneArticleCountById(Long id) {
        //非空校验
        if (id == null || id <= 0) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //查询用户信息
        User user = userMapper.selectByPrimaryKey(id);
        if (user == null) {
            //打印日志
            log.warn(ResultCode.ERROR_SERVICES.toString(),"user id:{}",id);
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
        //更新用户的发帖数量
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setArticleCount(user.getArticleCount() + 1);
        //更新数据库
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if (row != 1) {
            //打印日志
            log.warn(ResultCode.FAILED.toString() + ",更新失败");
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }


    }

    @Override
    public void subOneArticleCountById(Long id) {
        //非空校验
        if (id == null || id <= 0) {
            //打印日志
            log.warn(ResultCode.FAILED_BOARD_ARTICLE_COUNT.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_BOARD_ARTICLE_COUNT));
        }
        //查询用户信息
        User user = userMapper.selectByPrimaryKey(id);
        if (user == null) {
            //打印日志
            log.warn(ResultCode.ERROR_SERVICES.toString(),"user id:{}",id);
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
        //更新用户的发帖数量
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setArticleCount(user.getArticleCount() - 1);

        if (updateUser.getArticleCount() < 0) {

            updateUser.setArticleCount(0);
        }
        //更新数据库
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if (row != 1) {
            //打印日志
            log.warn(ResultCode.FAILED.toString() + ",删除失败");
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
        }
    }

    @Override
    public void modifyInfo(User user) {
       //非空校验
       if (user == null || user.getId() == null || user.getId() <= 0) {
           //打印日志
           log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
           //抛出异常
           throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
       }
       //校验用户是否存在
        User currentUser = userMapper.selectByPrimaryKey(user.getId());
        if (currentUser == null) {
            //打印日志
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        //对传入的参数进行一一校验
        //定义一个标志位进行校验
        boolean checkFlg = false;
        //构造当前用来更新的用户,防止用户传入其他的属性，
        //当使用动态SQL进行更新的时候，未经过校验的字段对数据库进行覆盖的操作
        User updateUser = new User();
        //设置用户id
        updateUser.setId(user.getId());
        //对每个参数进行校验并赋值
        //对用户名进行校验
        if (StringUtils.hasLength(user.getUsername())
            && !currentUser.getUsername().equals(user.getUsername())) {
            
            //对传入的用户名进行唯一性校验
            User cheakUser = userMapper.selectByUserName(user.getUsername());
            if (cheakUser != null) {
                //当前用户已经存在，
                //打印日志
                log.warn(ResultCode.FAILED_USER_EXISTS.toString());
                //抛出异常
                throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_EXISTS));
            }
            //用户名唯一，可以修改
            updateUser.setUsername(user.getUsername());
            //更新标志位
            checkFlg = true;
        }
        //对nickname进行校验
        if (StringUtils.hasLength(user.getNickname())
            && !currentUser.getNickname().equals(user.getNickname())) {

            //设置nickname
            updateUser.setNickname(user.getNickname());
            //更新标志位
            checkFlg = true;
        }
        //对gender进行校验
        if (user.getGender() != null && !currentUser.getGender().equals(user.getGender())) {
            //设置gender
            updateUser.setGender(user.getGender());
            //合法性校验
            if (updateUser.getGender() > 2 || updateUser.getGender() < 0) {
                updateUser.setGender((byte) 2);
            }
            //更新标准为
            checkFlg = true;
        }
        //对emil进行校验
        if (StringUtils.hasLength(user.getEmail())
                && !user.getEmail().equals(currentUser.getEmail())) {

            // 设置email
            updateUser.setEmail(user.getEmail());
            // 更新标志位
            checkFlg = true;
        }
        //对phoneNum进行校验
        if (StringUtils.hasLength(user.getPhoneNum())
                && !user.getPhoneNum().equals(currentUser.getPhoneNum())) {

            //设置phoneNum
            updateUser.setPhoneNum(user.getPhoneNum());
            //更新标志位
            checkFlg = true;
        }
        //对remark进行校验
        if (StringUtils.hasLength(user.getRemark())
                && !user.getRemark().equals(currentUser.getRemark())) {

            //更新remark
            updateUser.setRemark(user.getRemark());
            //更新标志位
            checkFlg = true;
        }
        //对checkFlg进行判断
        if (!checkFlg) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //调用dao
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if (row != 1) {
            //打印日志
            log.warn(ResultCode.ERROR_SERVICES.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }

    }

    @Override
    public void modifyPassword(Long id, String newPassword, String oldPassword) {
        //非空校验
        if (id == null || id <= 0 || StringUtil.isEmpty(newPassword) || StringUtil.isEmpty(oldPassword)) {
            //非空校验
            if (id == null || id <= 0) {
                //打印日志
                log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
                //抛出异常
                throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
            }
            //查询用户信息
            User user = userMapper.selectByPrimaryKey(id);
            if (user == null || user.getDeleteState() == 1) {
                //打印日志
                log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
                //抛出异常
                throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
            }
            //校验老密码是否正确
            //对老密码进行加密，获取密文
            String oldEncryptPassword = MD5Util.md5Salt(oldPassword, user.getSalt());
            if (!oldEncryptPassword.equalsIgnoreCase(user.getPassword())) {
                //打印日志
                log.warn(ResultCode.FAILED.toString());
                //抛出异常
                throw new ApplicationException(AppResult.failed(ResultCode.FAILED));
            }
            //重新生成新的随机盐值
            String salt = UUIDUtil.UUID_32();
            //生成新密码的密文
            String encryptPassword = MD5Util.md5Salt(newPassword,salt);
            //构造更新对象
            User updateUser = new User();
            updateUser.setId(user.getId()); //用户id
            updateUser.setSalt(salt);  //新的盐值
            updateUser.setPassword(encryptPassword);  //新密码的密文
            Date date = new Date();
            updateUser.setUpdateTime(date);  //更新时间
            //调用到
            int row = userMapper.updateByPrimaryKeySelective(updateUser);
            if (row != 1) {
                //打印日志
                log.warn(ResultCode.ERROR_SERVICES.toString());
                //抛出异常
                throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
            }
        }
    }

}
